import { PropType, computed, defineComponent, h } from "vue";
import { FeatherCheckCircle, FeatherXCircle } from "cui-vue-icons/feather";

export interface StrokeProps {
    percent: number
    color: string
}

type ProgressProps = {
    hidePercent?: boolean,
    status?: 'normal'|'error'|'active'|'success',
    value?: number,
    strokeWidth?: number,
    textInside?: boolean,
    infoRender?: (status: any, value: any) => any,
    strokeColor?: string | string[] | StrokeProps[],
    type?: 'line'|'circle',
    radius?: number,
    max?: number,
}

export default defineComponent({
    name: "CProgress",
    props: {
        hidePercent: { type: Boolean as PropType<ProgressProps['hidePercent']> },
        status: { type: String as PropType<ProgressProps['status']> },
        value: { type: Number as PropType<ProgressProps['value']> },
        strokeWidth: { type: Number as PropType<ProgressProps['strokeWidth']> },
        textInside: { type: Boolean as PropType<ProgressProps['textInside']> },
        infoRender: { type: Function as PropType<ProgressProps['infoRender']> },
        strokeColor: { type: [String, Array] as PropType<ProgressProps['strokeColor']> },
        type: { type: String as PropType<ProgressProps['type']> },
        radius: { type: Number as PropType<ProgressProps['radius']> },
        max: { type: Number as PropType<ProgressProps['max']> },
    },
    setup: (props) => {
        const max = computed(() => props.max ?? 100);
        const value = computed(() => {
            if (props.value < 0) {
                return 0;
            }
            if (props.value >= max.value) {
                return max.value;
            }
            return props.value ?? 0;
        });
        const strokeWidth = props.strokeWidth ?? 10;
        const type = props.type ?? 'line';
        const radius = computed(() => props.radius ?? 60);
        const status = computed(() => {
            if (value.value === max.value) {
                return 'finished';
            }
            return props.status ?? 'normal';
        });
        const classList = computed(() => ({
            'cm-progress': true,
            'cm-progress-hide-info': props.hidePercent,
            [`cm-progress-${status.value}`]: !!status.value,
            [`cm-progress-${type}`]: !!type,
        }));
        const width = computed(() => `${value.value >= max.value ? max.value : value.value}%`);
        const text = computed(() => {
            const sta = status.value;
            const size = type === 'line' ? 12 : 24;
            if (props.infoRender) {
                return props.infoRender(sta, value.value);
            }
            if (sta === 'finished') {
                return <FeatherCheckCircle size={size}/>;
            }
            if (sta === 'error') {
                return <FeatherXCircle size={size}/>;
            }
            return `${value.value >= max.value ? max.value : value.value}%`;
        });

        const style = computed(() => {
            const obj: any = {
                width: width.value,
                height: `${strokeWidth}px`
            };
            if (props.strokeColor) {
                if (typeof props.strokeColor === 'string') {
                    obj['background-color'] = props.strokeColor;
                }
                if (props.strokeColor instanceof Array) {
                    const length = props.strokeColor.length;
                    const arr = (props.strokeColor as string[]).map((color: string, index: number) => {
                        return color + ' ' + (index / length) * 100 + '%';
                    });
                    obj['background-image'] = `linear-gradient(to right, ${arr.join(',')})`;
                }
            }
            return obj;
        });

        // 计算当前角度对应的弧度值
        const rad = 2 * Math.PI;

        // 极坐标转换成直角坐标
        const x = computed(() => (Math.sin(rad) * radius.value).toFixed(2));
        const y = computed(() => -(Math.cos(rad) * radius.value).toFixed(2));
        const tx = computed(() => radius.value + strokeWidth / 2);

        // path 属性 A 61 61 0 1 1 -0 61 A 61 61 0 1 1 -0 -61
        const descriptions = () => ['M', 0, -radius.value, 'A', radius.value, radius.value, 0, 1, 1, x.value, -y.value, 'A', radius.value, radius.value, 0, 1, 1, x.value, y.value];

        const circleStyle = computed(() => {
            const percent = () => value.value >= max.value ? 1 : value.value / max.value;
            const dd = () => rad * radius.value;
            const offset = () => dd() * (1 - percent());

            const obj: any = {
                'stroke-dashoffset': `${offset()}`,
                'stroke-dasharray': dd()
            };
            if (props.strokeColor) {
                if (typeof props.strokeColor === 'string') {
                    obj['stroke'] = props.strokeColor;
                }
                if (props.strokeColor instanceof Array) {
                    for (let i = 0; i < props.strokeColor.length; i++) {
                        const stroke = props.strokeColor[i] as StrokeProps;

                        if (percent() * 100 >= stroke.percent) {
                            obj['stroke'] = stroke.color;
                        }
                    }
                }
            }
            return obj;
        });

        return () => <div class={classList.value}>
            <div class="cm-progress-outer">
                <div class="cm-progress-inner">
                    {
                        type === 'line'
                            ? <div class="cm-progress-bar" style={style.value}>
                                {
                                    props.textInside
                                        ? <span class="cm-progress-info">{`${value.value >= max.value ? max.value : value.value}%`}</span>
                                        : null
                                }
                            </div>
                            : type === 'circle'
                                ? <svg width="100%" height="100%" version="1.1"
                                    xmlns="http://www.w3.org/2000/svg" style={{display: 'block', width: (2 * radius.value + strokeWidth) + 'px', height: (2 * radius.value + strokeWidth) + 'px'}}>
                                    <circle cx={tx.value} cy={tx.value} r={radius.value} stroke="#f3f3f3"
                                        stroke-width={strokeWidth} fill-opacity="0" />
                                    <path class="cm-progress-bar-path"
                                        d={descriptions().join(' ')}
                                        stroke-linecap="round"
                                        stroke-width={strokeWidth}
                                        fill-opacity="0"
                                        transform={`translate(${tx.value},${tx.value})`}
                                        style={circleStyle.value}
                                    />
                                </svg>
                                : null
                    }
                </div>
            </div>
            {
                !props.textInside
                    ? <span class="cm-progress-info">{text.value}</span>
                    : null
            }
        </div>;
    }
});
